﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework;

namespace OneLine.Components
{
    /// <summary>
    /// Helper for reading input from keyboard and gamepad. This class tracks both
    /// the current and previous state of both input devices, and implements query
    /// properties for high level input actions such as "move up through the menu"
    /// or "pause the game".
    /// </summary>
    public class Input
    {
        #region Fields

        public KeyboardState CurrentKeyboardState;
        public GamePadState CurrentGamePadState;

        public KeyboardState LastKeyboardState;
        public GamePadState LastGamePadState;
#if !XBOX360
        public MouseState CurrentMouseState;
        public MouseState LastMouseState;
        public bool IsMouseZoom = false;
#endif
        Vector2 cursorPosition;
        Vector2 normalizedCursorPosition;
        #endregion

        #region Properties
        public Vector2 CursorPosition
        {
            get { return cursorPosition; }
            set { cursorPosition = value; }
        }

        public Vector2 NormalizedCursorPosition
        {
            get { return normalizedCursorPosition; }
            set { normalizedCursorPosition = value; }
        }

        public bool InGameSelect
        {
            get
            {
                bool mouseClicked = false;
#if !XBOX360
                mouseClicked = (CurrentMouseState.LeftButton == ButtonState.Released &&
                    LastMouseState.LeftButton == ButtonState.Pressed);
#endif

                return mouseClicked || (CurrentGamePadState.Buttons.A == ButtonState.Pressed &&
                        LastGamePadState.Buttons.A == ButtonState.Released);
            }
        }

        /// <summary>
        /// Checks for a "menu up" input action (on either keyboard or gamepad).
        /// </summary>
        public bool MenuUp
        {
            get
            {
                return IsNewKeyPress(Keys.Up) ||
                       (CurrentGamePadState.DPad.Up == ButtonState.Pressed &&
                        LastGamePadState.DPad.Up == ButtonState.Released) ||
                       (CurrentGamePadState.ThumbSticks.Left.Y > 0 &&
                        LastGamePadState.ThumbSticks.Left.Y <= 0);
            }
        }


        /// <summary>
        /// Checks for a "menu down" input action (on either keyboard or gamepad).
        /// </summary>
        public bool MenuDown
        {
            get
            {
                return IsNewKeyPress(Keys.Down) ||
                       (CurrentGamePadState.DPad.Down == ButtonState.Pressed &&
                        LastGamePadState.DPad.Down == ButtonState.Released) ||
                       (CurrentGamePadState.ThumbSticks.Left.Y < 0 &&
                        LastGamePadState.ThumbSticks.Left.Y >= 0);
            }
        }


        /// <summary>
        /// Checks for a "menu select" input action (on either keyboard or gamepad).
        /// </summary>
        public bool MenuSelect
        {
            get
            {
                return IsNewKeyPress(Keys.Space) ||
                       IsNewKeyPress(Keys.Enter) ||
                       (CurrentGamePadState.Buttons.A == ButtonState.Pressed &&
                        LastGamePadState.Buttons.A == ButtonState.Released) ||
                       (CurrentGamePadState.Buttons.Start == ButtonState.Pressed &&
                        LastGamePadState.Buttons.Start == ButtonState.Released);
            }
        }


        /// <summary>
        /// Checks for a "menu cancel" input action (on either keyboard or gamepad).
        /// </summary>
        public bool MenuCancel
        {
            get
            {
                return IsNewKeyPress(Keys.Escape) ||
                       (CurrentGamePadState.Buttons.B == ButtonState.Pressed &&
                        LastGamePadState.Buttons.B == ButtonState.Released) ||
                       (CurrentGamePadState.Buttons.Back == ButtonState.Pressed &&
                        LastGamePadState.Buttons.Back == ButtonState.Released);
            }
        }


        /// <summary>
        /// Checks for a "pause the game" input action (on either keyboard or gamepad).
        /// </summary>
        public bool PauseGame
        {
            get
            {
                return IsNewKeyPress(Keys.Escape) ||
                       (CurrentGamePadState.Buttons.Back == ButtonState.Pressed &&
                        LastGamePadState.Buttons.Back == ButtonState.Released) ||
                       (CurrentGamePadState.Buttons.Start == ButtonState.Pressed &&
                        LastGamePadState.Buttons.Start == ButtonState.Released);
            }
        }


        public bool ZoomIn
        {
            get
            {
#if !XBOX360
                if ((CurrentMouseState.ScrollWheelValue - LastMouseState.ScrollWheelValue) > 0)
                    IsMouseZoom = true;
                return IsKeyDown(Keys.PageUp) ||
                       (CurrentGamePadState.DPad.Up == ButtonState.Pressed) || ((CurrentMouseState.ScrollWheelValue - LastMouseState.ScrollWheelValue) > 0);
#else
                return IsKeyDown(Keys.PageUp) ||
                       (CurrentGamePadState.DPad.Up == ButtonState.Pressed);
#endif
            }
        }

        public bool ZoomOut
        {
            get
            {
#if !XBOX360
                if ((CurrentMouseState.ScrollWheelValue - LastMouseState.ScrollWheelValue) < 0)
                    IsMouseZoom = true;
                return IsKeyDown(Keys.PageDown) ||
                       (CurrentGamePadState.DPad.Down == ButtonState.Pressed) || ((CurrentMouseState.ScrollWheelValue - LastMouseState.ScrollWheelValue) < 0);
#else
                return IsKeyDown(Keys.PageDown) ||
                       (CurrentGamePadState.DPad.Down == ButtonState.Pressed);
#endif


            }
        }



        #endregion



        #region Methods


        /// <summary>
        /// Reads the latest state of the keyboard and gamepad.
        /// </summary>
        public void Update()
        {
            LastKeyboardState = CurrentKeyboardState;
            LastGamePadState = CurrentGamePadState;

            CurrentKeyboardState = Keyboard.GetState();
            CurrentGamePadState = GamePad.GetState(PlayerIndex.One);
#if !XBOX360
            LastMouseState = CurrentMouseState;
            CurrentMouseState = Mouse.GetState();

            cursorPosition.X = CurrentMouseState.X;
            cursorPosition.Y = CurrentMouseState.Y;
#endif
        }


        /// <summary>
        /// Helper for checking if a key was newly pressed during this update.
        /// </summary>
        bool IsNewKeyPress(Keys key)
        {
            return (CurrentKeyboardState.IsKeyDown(key) &&
                    LastKeyboardState.IsKeyUp(key));
        }

        bool IsKeyDown(Keys key)
        {
            return (CurrentKeyboardState.IsKeyDown(key));
        }



        #endregion
    }
}
